﻿using Away.IdentityServer.Core.Utils;

namespace Away.IdentityServer.Core.Repositories.Impl;

[ServiceInject(ServiceLifetime.Scoped)]
public class ApiResourceRepository : ConfigurationRepository, IApiResourceRepository
{
    public ApiResourceRepository(ConfigurationDbContext context) : base(context)
    {
    }

    public IResult Page(ApiResourceSearch search)
    {
        var where = CondBuilder.New<ApiResource>(true)
              .And(!string.IsNullOrWhiteSpace(search.Name), o => o.Name.Contains(search.Name!));
        var query = Query<ApiResource>()
            .Include(o => o.Properties)
            .Include(o => o.UserClaims)
            .Include(o => o.Secrets)
            .Include(o => o.Scopes)
            .Where(where);
        var total = query.Count();
        var items = query.OrderBy(o => o.Id).Page(search).ToList();
        return ApiResult.Page(total, items);
    }

    public void Remove(List<int> ids)
    {
        var items = Query<ApiResource>().Where(o => ids.Any(oo => oo == o.Id)).ToArray();
        if (items.Length == 0)
        {
            return;
        }
        Remove(items);
        Save();
    }

    public void Save(ApiResource model)
    {
        Update(model);
        Save();

        var propertyIds = model.Properties.Select(o => o.Id);
        var claimIds = model.UserClaims.Select(o => o.Id);
        var secretIds = model.Secrets.Select(o => o.Id);
        var scopeIds = model.Scopes.Select(o => o.Id);

        var sql = SqlBuilder.New();
        sql.Delete("\"ApiResourceProperties\"")
            .Where($"\"ApiResourceId\"={model.Id}")
            .And(propertyIds.Any(), $"\"Id\" NOT IN ({string.Join(",", propertyIds)})")
            .End();

        sql.Delete("\"ApiResourceClaims\"")
            .Where($"\"ApiResourceId\"={model.Id}")
            .And(claimIds.Any(), $"\"Id\" NOT IN ({string.Join(",", claimIds)})")
            .End();

        sql.Delete("\"ApiResourceSecrets\"")
           .Where($"\"ApiResourceId\"={model.Id}")
           .And(secretIds.Any(), $"\"Id\" NOT IN ({string.Join(",", secretIds)})")
           .End();

        sql.Delete("\"ApiResourceScopes\"")
           .Where($"\"ApiResourceId\"={model.Id}")
           .And(scopeIds.Any(), $"\"Id\" NOT IN ({string.Join(",", scopeIds)})")
        .End();

        DB.Database.ExecuteSqlRaw(sql.ToSql());
    }
}
